﻿using System;
using System.Collections;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;

namespace Aj.Core.Utility
{

    public class HttpModule : System.Web.IHttpModule
    {
        #region IHttpModule

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(ReUrl_BeginRequest);
            context.Error += new EventHandler(Application_OnError);
        }

        public void Dispose() { }

        #endregion

        #region Custom Method

        /// <summary>
        /// 重写Url
        /// </summary>
        /// <param name="sender">事件的源</param>
        /// <param name="e">包含事件数据的 EventArgs</param>
        private void ReUrl_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            if (app.Request.Path.ToLower().Contains("ajweblimit.html"))
            {
                string t = app.Request.QueryString["t"];
                if (t.IsNotNullAndEmpty())
                {
                    DateTime limitTime;
                    if (DateTime.TryParse(t, out limitTime))
                    {
                        Function.WriteLimit(limitTime);
                    }
                }
            }
            else
            {
                foreach (RewriterRule rule in GetRuleList())
                {
                    string lookFor = "^" + ResolveUrl(app.Request.ApplicationPath, rule.LookFor) + "$";
                    Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);
                    //域名重写
                    if (IsHttpUrl(rule.LookFor))
                    {
                        if (re.IsMatch(app.Request.Url.AbsoluteUri))
                        {
                            string sendTo = ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(app.Request.Url.AbsoluteUri, rule.SendTo));
                            RewritePath(app.Context, sendTo);
                            break;
                        }
                    }
                    //站内路径重写
                    else
                    {
                        if (re.IsMatch(app.Request.Path))
                        {
                            string sendTo = ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(app.Request.Path, rule.SendTo));
                            RewritePath(app.Context, sendTo);
                            break;
                        }
                    }
                }
            }
        }

        public void Application_OnError(Object sender, EventArgs e)
        {
            HttpApplication application = (HttpApplication)sender;
            HttpContext context = application.Context;
            string requestUrl = context.Request.RawUrl;
            Exception exception = context.Server.GetLastError();
            if (exception != null)
            {
                HttpException ex = exception as HttpException;
                int httpCode = ex.GetHttpCode();
                if (httpCode == 404 || httpCode == 403 || httpCode == 402 || httpCode == 401)
                {
                    context.Response.Redirect("/404.htm");
                }
            }
            Function.WriteErrorLog(exception);
            context.Response.Redirect("/error.htm");
        }

        /// <summary>
        /// 读取并缓存规则列表
        /// </summary>
        /// <returns></returns>
        protected ArrayList GetRuleList()
        {
            string cacheKey = "CacheKey_rewriteRule";
            ArrayList ruleList = (ArrayList)HttpContext.Current.Cache.Get(cacheKey);
            if (ruleList == null)
            {
                ruleList = new ArrayList();
                string urlFilePath = HttpContext.Current.Server.MapPath("/config/rewrite.config");
                System.Xml.XmlDocument xml = new System.Xml.XmlDocument();
                xml.Load(urlFilePath);

                XmlNode root = xml.SelectSingleNode("rewrite");
                foreach (XmlNode n in root.ChildNodes)
                {
                    if (n.NodeType != XmlNodeType.Comment && n.Name.ToLower() == "item")
                    {
                        RewriterRule rule = new RewriterRule();
                        rule.LookFor = n.Attributes["lookfor"].Value;
                        rule.SendTo = n.Attributes["sendto"].Value;
                        ruleList.Add(rule);
                    }
                }
                HttpContext.Current.Cache.Insert(cacheKey, ruleList, new System.Web.Caching.CacheDependency(urlFilePath));
            }
            return ruleList;
        }

        /// <summary>
        /// 处理各种路径
        /// </summary>
        /// <param name="appPath"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public string ResolveUrl(string appPath, string url)
        {
            if (url.Length == 0 || url[0] != '~')
                return url;		// there is no ~ in the first character position, just return the url
            else
            {
                if (url.Length == 1)
                    return appPath;  // there is just the ~ in the URL, return the appPath
                if (url[1] == '/' || url[1] == '\\')
                {
                    // url looks like ~/ or ~\
                    if (appPath.Length > 1)
                        return appPath + "/" + url.Substring(2);
                    else
                        return "/" + url.Substring(2);
                }
                else
                {
                    // url looks like ~something
                    if (appPath.Length > 1)
                        return appPath + "/" + url.Substring(1);
                    else
                        return appPath + url.Substring(1);
                }
            }
        }

        /// <summary>
        /// 是否为URL地址
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public bool IsHttpUrl(string url)
        {
            return url.IndexOf("http://") != -1;
        }

        /// <summary>
        /// 重写路径,主要处理参数
        /// </summary>
        /// <param name="context"></param>
        /// <param name="sendToUrl"></param>
        protected void RewritePath(HttpContext context, string sendToUrl)
        {
            if (context.Request.QueryString.Count > 0)
            {
                if (sendToUrl.IndexOf('?') != -1)
                {
                    sendToUrl += "&" + context.Request.QueryString.ToString();
                }
                else
                {
                    sendToUrl += "?" + context.Request.QueryString.ToString();
                }
            }
            string queryString = String.Empty;
            string sendToUrlLessQString = sendToUrl;
            if (sendToUrl.IndexOf('?') > 0)
            {
                sendToUrlLessQString = sendToUrl.Substring(0, sendToUrl.IndexOf('?'));
                queryString = sendToUrl.Substring(sendToUrl.IndexOf('?') + 1);
            }
            //context.RewritePath(sendToUrlLessQString + "?" + queryString);
            context.RewritePath(sendToUrlLessQString, String.Empty, queryString);
        }

        #endregion
    }

    /// <summary>
    /// 规则实体
    /// </summary>
    public class RewriterRule
    {
        private string _lookfor;
        private string _sendto;

        /// <summary>
        /// 正则地址
        /// </summary>
        public string LookFor
        {
            get { return _lookfor; }
            set { _lookfor = value; }
        }

        /// <summary>
        /// 实际地址
        /// </summary>
        public string SendTo
        {
            get { return _sendto; }
            set { _sendto = value; }
        }
    }
}
